Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: unsynchronized concurrent wasm calls #1155

Merged
merged 6 commits into from
Dec 17, 2024

Conversation

xJonathanLEI
Copy link
Contributor

Concurrent calls to the wasm module where at least one call borrows CartridgeAccount mutably causes wasm-bindgen's runtime borrow checker to throw:

recursive use of an object detected which would lead to unsafe aliasing in rust

This PR fixes it by:

  1. Reducing unnecessary borrowing: A new CartridgeAccountWithMeta type is now used for reading fixed values. This type is only ever borrowed immutably, so concurrent accesses are fine.
  2. Guarding the inner controller value with a Promise-backed WasmMutex, and changing all entrypoint signatures to use &self instead of &mut self.

Note

Using a mutex for all calls, as implemented in this PR, is an overkill. A more ideal implementation would be something like a RwLock such that concurrent reads are still allowed.

Copy link

vercel bot commented Dec 16, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
ui ✅ Ready (Inspect) Visit Preview Dec 17, 2024 2:38pm
ui-next ✅ Ready (Inspect) Visit Preview Dec 17, 2024 2:38pm

@@ -73,7 +85,7 @@ function Home() {
return <></>;
}

if (controller.session(policies)) {
if (hasSessionForPolicies) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm does this migration to async maintain the same behavior? It seems on initial render it will be false and proceed now. I think we might need a loading state for the intermediate state, when the useEffect hasn't been executed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right that this is technically not the exact same behaviour as the sync version. However, I think under a real world scenario it's very unlikely that users would ever run into the case where the loading state is observable. This is because when .connect() is called, it's highly unlikely that the host app would somehow also be blocking the wasm module. After all, .connect() is likely their first function call before doing anything real. This means that despite being async, the hasSessionForPolicies state would instantaneously be set to its desired value.

That said, I can certainly add a loading state. It's just that given the unlikeliness of it being actually observable as discussed above, I'd go for something very primitive. I will test it by artificially delaying the wasm call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright I just pushed a commit adding a loading screen using the existing <PageLoading /> component:

@xJonathanLEI
Copy link
Contributor Author

Got conflicts. Rebasing now.

@xJonathanLEI
Copy link
Contributor Author

Rebased.

@xJonathanLEI xJonathanLEI merged commit 2727d65 into main Dec 17, 2024
18 checks passed
@xJonathanLEI xJonathanLEI deleted the fix/wasm_internal_mutability branch December 17, 2024 15:08
@rsodre
Copy link

rsodre commented Dec 17, 2024

this is also happening on dojo.js torii client
will open an issue...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants